package com.apkcore.core.ext

import android.app.Activity
import android.app.ActivityManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.res.ColorStateList
import android.content.res.Resources
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.RippleDrawable
import android.os.Build
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.util.TypedValue
import android.view.MotionEvent
import android.view.View
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.core.graphics.Insets
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.apkcore.core.DoubleClickListener
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlin.math.roundToInt


fun View.setOnSingleAndDoubleClickListener(onDoubleClickListener: (View, Int) -> Unit) {
    DoubleClickListener.setOnSingleAndDoubleClickListener(this, onDoubleClickListener)
}

fun Int.sp2px(): Float {
    return TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_SP,
        this.toFloat(), Resources.getSystem().displayMetrics
    )
}

fun Int.px2sp(): Float {
    return this / Resources.getSystem().displayMetrics.scaledDensity
}

fun Int.dp2px(): Int {
    return TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        this.toFloat(), Resources.getSystem().displayMetrics
    ).toInt()
}

fun Int.px2dp(): Int {
//    TypedValue.deriveDimension()
    return (this / Resources.getSystem().displayMetrics.density).toInt()
}

/**
 * https://article.juejin.cn/post/7252231214529282085
 * 沉浸式状态栏
 */
fun Activity.fullScreen() {
    WindowCompat.setDecorFitsSystemWindows(window, false)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        //当背景透明时去掉灰色蒙层
        window.isNavigationBarContrastEnforced = false
    }
    //导航栏背景颜色透明
    window.statusBarColor = Color.TRANSPARENT
    window.statusBarColor = Color.TRANSPARENT
    window.navigationBarColor = Color.TRANSPARENT
}

/**
 *
 * WindowInsetsCompat.Type参数解释：
 * WindowInsetsCompat.Type.ime();//键盘
 * WindowInsetsCompat.Type.displayCutout();//刘海屏
 * WindowInsetsCompat.Type.statusBars();//状态栏
 * WindowInsetsCompat.Type.navigationBars();//导航栏
 * WindowInsetsCompat.Type.captionBar();//标题栏
 * WindowInsetsCompat.Type.systemBars();//状态栏,导航栏和标题栏
 * WindowInsetsCompat.Type.systemGestures();//系统手势
 * WindowInsetsCompat.Type.mandatorySystemGestures();//强制性系统手势
 * WindowInsetsCompat.Type.tappableElement();//可点击区域
 */
fun View.getSystemWindow(callback: (Insets) -> Unit) {
    ViewCompat.setOnApplyWindowInsetsListener(this) { view, insets: WindowInsetsCompat ->
        val systemWindow = insets.getInsetsIgnoringVisibility(
            WindowInsetsCompat.Type.systemBars() or
                    WindowInsetsCompat.Type.displayCutout()
        )
        callback.invoke(systemWindow)
        insets
    }
}

fun Activity.setLightStatusBars(black: Boolean = true) {
    WindowCompat.getInsetsController(window, window.decorView).isAppearanceLightStatusBars = black
}

fun Fragment.setLightStatusBars(black: Boolean = true) {
    requireActivity().setLightStatusBars(black)
}

fun Context.getActionBarSize(defaultDp: Int = 44): Int {
    val actionBarSizeAttributeId = androidx.appcompat.R.attr.actionBarSize
    val typedValue = TypedValue()
    // 获取 actionBarSize 的值
    if (this.theme.resolveAttribute(actionBarSizeAttributeId, typedValue, true)) {
        return TypedValue.complexToDimensionPixelSize(
            typedValue.data,
            this.resources.displayMetrics
        )
    }
    return defaultDp.dp2px()
}

/**
 * 冷暖色
 */
fun Int.hue(): Boolean {
    val colorInt = this
    val red = Color.red(colorInt)
    val green = Color.green(colorInt)
    val blue = Color.blue(colorInt)

    val max = maxOf(red, green, blue)
    val min = minOf(red, green, blue)

    val hue = when (max) {
        min -> 0f
        red -> (60 * ((green - blue) / (max - min).toFloat()) + 360) % 360f
        green -> (60 * ((blue - red) / (max - min).toFloat()) + 120) % 360f
        else -> (60 * ((red - green) / (max - min).toFloat()) + 240) % 360f
    }
    val hue2 = hue.roundToInt()
    return hue2 in 0..60 || hue2 in 300..360
}

/**
 * 明暗度
 */
fun Int.brightness(): Boolean {
    val colorInt = this
    val red = Color.red(colorInt)
    val green = Color.green(colorInt)
    val blue = Color.blue(colorInt)

    val brightness = (red * 299 + green * 587 + blue * 114) / 1000
    Log.d("Int.brightness()", "brightness: $brightness")
//    return brightness > 125
    return brightness > 170
}

fun View.getCurrentActivity(): Activity? {
    val context = this.context
    while (context is Context) {
        if (context is Activity) {
            return context
        }
    }
    return null
}

/**
 * 点击增加一个透明度
 */
fun View.addColorMask(defaultColor: Int = Color.WHITE, clickedAlpha: Float = 0.2f) {
    val defaultAlpha = 0f

    var isPressed = false
    val color = background.let {
        if (it is ColorDrawable) {
            it.color
        } else {
            defaultColor
        }
    }
    Log.d("bsb", "addColorMask: $color")

    this.setOnTouchListener { view, motionEvent ->
        when (motionEvent.action) {
            MotionEvent.ACTION_DOWN -> {
                view.setBackgroundColor(color.withAlpha(clickedAlpha))
                isPressed = true
            }

            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                view.setBackgroundColor(color.withAlpha(defaultAlpha))
                if (isPressed && motionEvent.action == MotionEvent.ACTION_UP) {
//                    onClickListener.onClick(view)
                    performClick()
                }
                isPressed = false
            }
        }
        true
    }
}

fun Int.withAlpha(alpha: Float): Int {
    val alphaValue = (alpha * 255).toInt()
    return Color.argb(alphaValue, Color.red(this), Color.green(this), Color.blue(this))
}

/**
 * 点击增加一个水波纹
 */
fun View.addRippleEffect(defaultColor: Int = Color.WHITE, clickedAlpha: Float = 0.2f) {
    val color = background.let {
        if (it is ColorDrawable) {
            it.color
        } else {
            // 如果背景是 Drawable 类型，则根据需要进行处理
            defaultColor
        }
    }
    Log.d("bsb", "addRippleEffect: $color")

    // 创建波纹的颜色
    val rippleColor = ColorStateList.valueOf(color.withAlpha(clickedAlpha))

    // 创建波纹的形状
    val shape = android.graphics.drawable.GradientDrawable()
    shape.setColor(color) // 设置背景颜色
    shape.cornerRadius = 10f // 设置圆角半径

    // 创建波纹效果
    val rippleDrawable = RippleDrawable(rippleColor, null, shape)

    // 如果当前系统版本低于 API 21，使用 ColorDrawable 作为背景
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        setBackgroundDrawable(rippleDrawable)
    } else {
        background = rippleDrawable
    }
}

fun View.findBackgroundColor(): Int {
    var currentView: View? = this
    var backgroundColor = Color.TRANSPARENT

    while (currentView != null) {
        val backgroundDrawable = currentView.background
        if (backgroundDrawable is ColorDrawable) {
            backgroundColor = backgroundDrawable.color
            // 如果背景色不是透明，则找到了实际设置的背景色，退出循环
            if (backgroundColor != Color.TRANSPARENT) {
                break
            }
        }
        // 继续检查父级视图的背景色
        currentView = currentView.parent as? View
    }

    return backgroundColor
}

fun Context.isDebug(): Boolean {
    return applicationInfo != null && applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0
}

fun Context.isAppForeground(): Boolean {
    val activityManager = this.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    val appProcesses = activityManager.runningAppProcesses ?: return false
    for (appProcess in appProcesses) {
        if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
            appProcess.processName == this.packageName
        ) {
            return true
        }
    }
    return false
}

fun EditText.textChangeDuration(
    coroutineScope: CoroutineScope,
    timeout: Long = 300,
    action: (String) -> Unit
) {
    val et = this
    callbackFlow {
        val watcher = object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            }

            override fun afterTextChanged(s: Editable?) {
                s?.let {
                    trySend(s.toString())
                }
            }
        }
        et.addTextChangedListener(watcher)
        //在 flow 被 close 时调用，可以清理资源，一般必须要有
        awaitClose {
            et.removeTextChangedListener(watcher)
        }
    }.debounce(timeout).map {
        action(it)
    }.launchIn(coroutineScope)
}

fun Fragment.autoUnregister(
    register: (() -> Unit)? = null,
    registerEvent: Lifecycle.Event = Lifecycle.Event.ON_CREATE,
    unregisterEvent: Lifecycle.Event = Lifecycle.Event.ON_DESTROY,
    unregister: () -> Unit
) {
    lifecycle.addObserver(object : LifecycleEventObserver {
        override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
            when (event) {
                unregisterEvent -> {
                    unregister()
                }

                registerEvent -> {
                    register?.invoke()
                }

                else -> {}
            }
        }

    })
}

fun AppCompatActivity.autoUnregister(
    register: (() -> Unit)? = null,
    registerEvent: Lifecycle.Event = Lifecycle.Event.ON_CREATE,
    unregisterEvent: Lifecycle.Event = Lifecycle.Event.ON_DESTROY,
    unregister: () -> Unit
) {
    lifecycle.addObserver(object : LifecycleEventObserver {
        override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
            when (event) {
                unregisterEvent -> {
                    unregister()
                }

                registerEvent -> {
                    register?.invoke()
                }

                else -> {}
            }
        }
    })
}